package com.naiterui.ehp.bs.im.api;

import cn.hutool.json.JSONUtil;
import com.naiterui.common.redis.RedisUtil;
import com.naiterui.ehp.bp.constants.DoctorPatientRelation;
import com.naiterui.ehp.bp.constants.SwaggerTag;
import com.naiterui.ehp.bp.support.exception.PublicService;
import com.naiterui.ehp.bp.support.exception.ResponseVO;
import com.naiterui.ehp.bp.support.security.HeaderConstant;
import com.naiterui.ehp.bp.support.security.SettingConfig;
import com.naiterui.ehp.bp.support.utils.IpUtil;
import com.naiterui.ehp.bs.im.exception.ExceptionCodes;
import com.naiterui.ehp.bs.im.exception.NaiteruiIMException;
import com.naiterui.ehp.bs.im.network.protocl.Disturb;
import com.naiterui.ehp.bs.im.network.protocl.Replay;
import com.naiterui.ehp.bs.im.network.protocl.SessionParams;
import com.naiterui.ehp.bs.im.network.protocl.Shield;
import com.naiterui.ehp.bs.im.service.INaiteruiIMService;
import com.naiterui.ehp.bs.im.utils.Constants;
import com.naiterui.ehp.bs.im.vo.DisturbVO;
import com.naiterui.ehp.bs.im.vo.ImgTimeGroupVO;
import com.naiterui.ehp.bs.im.vo.MediaUploadVO;
import com.naiterui.ehp.bs.im.vo.MessageVO;
import com.naiterui.ehp.bs.im.vo.MqttConnectParam;
import com.naiterui.ehp.bs.im.vo.PageVO;
import com.naiterui.ehp.bs.im.vo.QueryHistoryCondVO;
import com.naiterui.ehp.bs.im.vo.ReplayVO;
import com.naiterui.ehp.bs.im.vo.SessionVO;
import com.naiterui.ehp.bs.im.vo.ShieldVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 上行消息接口处理类 负责信息的发送
 * 包括文件信息的发送以及多媒体信息的上传
 */
@Api(tags = {SwaggerTag.DOCTOR + SwaggerTag.IM, SwaggerTag.PATIENT + SwaggerTag.IM})
@RestController
public class MessageApi {

    /**
     * 日至输出类
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(MessageApi.class);

    private final INaiteruiIMService naiteruiIMService;

    public MessageApi(INaiteruiIMService naiteruiIMService) {
        this.naiteruiIMService = naiteruiIMService;
    }

    /**
     * 获取与MQTT Broker建立连接的参数
     *
     * @return
     */
    @ApiOperation(value = "获取与MQTT Broker建立连接的参数")
    @ApiImplicitParam(name = "userId", value = "获取参数的用户id（医生、患者）", paramType = "querey", dataType = "long",
            required = true)
    @RequestMapping(value = "/connect/params")
    public MqttConnectParam getMqttConnectionParams(Long userId, String token, HttpServletRequest request) throws Exception {
        if (userId == null) {
            throw new NaiteruiIMException(ExceptionCodes.CONNECT_USER_ID_IS_NULL);
        }
        // 获取平台信息
        int origin = this.getOrigin(request);
        String ip = IpUtil.getIp(request);
        // 只有当发送的是文本消息并且消息的内容中包含药品名字时才会数组才不会为空
        MqttConnectParam connParam = this.naiteruiIMService.getMqttConnectionParams(origin, userId, token, ip);
        return connParam;
    }

    /**
     * 消息发送接口 用于客户端的消息发送
     *
     * @return
     */
    @ApiOperation(value = "消息发送接口")
    @ApiImplicitParam(name = "message", value = "消息体json格式", paramType = "querey", dataType = "string", required = true)
    @PostMapping(value = "/chat/sendMessage")
    public ResponseVO<Object> sendMessage(String message, HttpServletRequest request) throws Exception {

        // 调用消息发送接口
        // 获取平台信息
        int origin = this.getOrigin(request);

        LOGGER.info("sendMessage:{},origin:{}.", message, origin);
        // 消息处理
        MessageVO result = this.naiteruiIMService.sendMessage(origin, message);
        if (result.getConsultPayStatus() != null) {
            Map<String, Object> consultCostMap = new HashMap<>();
            consultCostMap.put("doctorName", result.getDoctorName());
            consultCostMap.put("consultCost", result.getConsultPrice());
            if (result.getConsultPayStatus() == Constants.SESSION_PAY_STATUS_FAIL) {// 支付失败
                return PublicService.returnResponseVO(ExceptionCodes.SESSION_NEED_PAID, consultCostMap);
            }
            if (result.getConsultPayStatus() == Constants.SESSION_PAY_STATUS_PAYMENT_IN) {// 支付结果未确认
                return PublicService.returnResponseVO(ExceptionCodes.SESSION_BEING_PAID, consultCostMap);
            }
        }
        return PublicService.returnResponseVO(result);
    }

    /**
     * 文件上传接口 用于客户端发送多媒体文件 图片、音频、小视频 MessageSender.uploadMediaData()<BR>
     *
     * @return
     */
    @ApiOperation(value = "文件上传接口 用于客户端发送多媒体文件 图片、音频、小视频")
    @ApiImplicitParam(name = "file", value = "文件", paramType = "form", dataType = "__file", required = true)
    @PostMapping(value = "/chat/media/upload")
    public ResponseVO<String> uploadMediaData(MediaUploadVO mediaUpload, @RequestParam(value = "file", required = false) MultipartFile[] file,
                                              HttpServletRequest request) throws Exception {
        // 调用消息发送接口
        // 获取平台信息
        int origin = this.getOrigin(request);
        int platform = this.getPlatform(request);
        mediaUpload.setOrigin(origin);
        mediaUpload.setPlatform(platform);
        // 上传文件
        String fileURL = this.naiteruiIMService.uploadMediaData(mediaUpload, file);
        return PublicService.returnResponseVO(fileURL);
    }

    /**
     * 获取聊天历史记录 MessageSender.getChatHistory()<BR>
     *
     * @return
     */
    @ApiOperation(value = "获取聊天历史记录")
    @RequestMapping(value = "/chat/history")
    public PageVO getChatHistory(QueryHistoryCondVO vo, HttpServletRequest request) throws Exception {
        LOGGER.info("获取聊天历史记录");
        vo.setFromId(Long.valueOf(request.getParameter(SettingConfig.PATIENT_ID)));
        // 调用消息发送接口
        // 获取平台信息
        int origin = this.getOrigin(request);
        // 获取历史记录
        return this.naiteruiIMService.getChatHistory(origin, vo);
    }

    /**
     * 获取图片上传的历史记录
     *
     * @return
     */
    @ApiOperation(value = "获取图片上传的历史记录")
    @RequestMapping(value = "/chat/history/imgUpload")
    public PageVO<ImgTimeGroupVO> getImageUploadHistory(String token, Long patientId, Long doctorId, Integer page, Integer num) throws Exception {

        // 调用消息发送接口
        return this.naiteruiIMService.getImageUploadHistory(token, patientId, doctorId, page, num);
    }

    /**
     * 设置 勿扰模式
     */
    @ApiOperation(value = "设置 勿扰模式")
    @RequestMapping(value = "/disturb/set")
    public void setDistrub(Disturb disturb, int operate) throws Exception {

        // 调用消息发送接口
        this.naiteruiIMService.setDisturb(disturb, operate);
    }

    /**
     * 获取勿扰模式 状态 MessageSender.getDistrub()
     *
     * @return
     */
    @ApiOperation(value = "获取勿扰模式 状态")
    @RequestMapping(value = "/disturb")
    public DisturbVO getDistrub(Long userId) throws Exception {

        // 调用消息发送接口
        return this.naiteruiIMService.getDisturb(userId);
    }

    /**
     * 设置屏蔽某用户 MessageSender.setShield()
     */
    @ApiOperation(value = "设置屏蔽某用户")
    @RequestMapping(value = "/shield/set")
    public void setShield(Shield shield, int operate) throws Exception {

        // 调用消息发送接口
        this.naiteruiIMService.setShield(shield, operate);
    }

    /**
     * 屏蔽用户列表查询 MessageSender.getShield()
     *
     * @return
     */
    @ApiOperation(value = "屏蔽用户列表查询")
    @RequestMapping(value = "/shield")
    public ShieldVO getShield(Long userId) throws Exception {

        // 调用消息发送接口
        return this.naiteruiIMService.getShield(userId);
    }

    /**
     * 自动 回复接口
     *
     * @return
     */
    @ApiOperation(value = "自动 回复接口")
    @RequestMapping(value = "/replay")
    public ReplayVO replay(Replay replay, Integer operate) throws Exception {

        // 调用消息发送接口
        return this.naiteruiIMService.setOrGetReplay(replay, operate);
    }

    /**
     * 会话列表
     *
     * @return
     */
    @ApiOperation(value = "会话列表")
    @RequestMapping(value = "/session/list")
    public PageVO<?> sessionList(SessionParams params) throws Exception {

        Long doctorId = params.getDoctorId();
        Long patientId = params.getPatientId();

        /*
         * 检测患者是否被删除
         */
        String doctorPatientRelationRedisKey = DoctorPatientRelation.getRedisKey(doctorId, patientId);
        if (RedisUtil.keyOps().existsKey(doctorPatientRelationRedisKey)) {
            throw new NaiteruiIMException(ExceptionCodes.PATIENT_HADBEEN_DELETE_TODOC_ERROR);
        }

        // 查询session分页数据
        return this.naiteruiIMService.findSessionPageList(params);
    }

    /**
     * 会话详情信息
     *
     * @return
     */
    @ApiOperation(value = "会话详情信息")
    @RequestMapping(value = "/session/details")
    public PageVO<?> sessionDetails(HttpServletRequest request, String sessionId, Integer pageNo, Integer pageSize, Long endTime,
                                    Long doctorId, Long patientId) throws Exception {
        LOGGER.info("session details, sessionId: {}, pageNo: {}, pageSize: {}, endTime: {}, doctorId: {}, patientId: {}", sessionId, pageNo, pageSize, endTime, doctorId, patientId);
        // 获取应用来源信息
        int origin = this.getOrigin(request);
        return this.naiteruiIMService.findMessagesBySession(sessionId, pageNo, pageSize, endTime, origin, doctorId, patientId);
    }

    /**
     * 结束会话接口
     *
     * @return
     */
    @ApiOperation(value = "图文咨询结束会话", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sessionId", value = "会话Id", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "doctorId", value = "医生Id", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "patientId", value = "患者Id", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "freeFlag", value = "是否免单 0:免费;1:收费;", required = true, dataType = "int", paramType = "query")
    })
    @RequestMapping(value = "/session/finish")
    public SessionVO sessionDetails(SessionParams params) throws Exception {
        LOGGER.info("session finish, SessionParams:{}", JSONUtil.toJsonStr(params));
        return this.naiteruiIMService.finishSession(params);
    }

    /**
     * 更新支付类型
     *
     * @return
     */
    @ApiOperation(value = "更新支付类型")
    @RequestMapping(value = "/session/status")
    public SessionVO sessionStatus(String sessionId) throws Exception {
        LOGGER.info("session status, sessionId:{}", sessionId);
        return this.naiteruiIMService.findSessionStatus(sessionId);
    }

    /**
     * 公共通知
     */
    @ApiOperation(value = "公共通知")
    @RequestMapping(value = "/notice/public")
    public void publicNotice(String message, String userType) throws Exception {
        this.naiteruiIMService.publicNotice(message, userType);
    }

    /**
     * 私人通知
     */
    @ApiOperation(value = "私人通知")
    @RequestMapping(value = "/notice/private")
    public void privateNotice(String message, Long userId, Boolean force, String userType) throws Exception {
        LOGGER.info("userId:{},userType:{},force:{}", userId, userType, force);
        this.naiteruiIMService.privateNotice(message, userId, force, userType);
    }

    @ApiOperation(value = "私人通知")
    @GetMapping(value = "/notice/private")
    public void get(String message, Long userId, Boolean force, String userType) throws Exception {
        LOGGER.info("userId:{},userType:{},force:{}", userId, userType, force);
        this.naiteruiIMService.privateNotice(message, userId, force, userType);
    }

    //=======================================================

    /**
     * 从请求的header中获取平台信息 MessageSender.getOrigin()
     */
    private int getOrigin(HttpServletRequest request) throws NaiteruiIMException {

        // 从header中获取平台参数
        String originHeader = request.getHeader(HeaderConstant.HEADER_ORIGIN);

        // 校验参数合法性
        return this.naiteruiIMService.checkOrigin(originHeader);
    }

    /**
     * MessageSender.getPlatform()
     */
    private int getPlatform(HttpServletRequest request) throws NaiteruiIMException {
        // 从header中获取平台参数
        String platformHeader = request.getHeader(HeaderConstant.HEADER_PLATFORM);

        // 校验参数合法性
        return this.naiteruiIMService.checkPlatform(platformHeader);
    }
}
